﻿Imports System.Reflection
Imports System.Reflection.Emit
Imports VBParser

Namespace Compiler.Semantic

    Public MustInherit Class TypeDescription
        Inherits ContainerSyntaxNodeDescription

        Public Sub New(ByVal parent As NameContainer)
            MyBase.New(parent)

            'default is not a nested type
            m_isNested = False
            m_nestedTypes = New BindingTable(Of TypeDescription)
        End Sub

        Public Overrides ReadOnly Property IdentifyBinder() As Binder
            Get
                Return New TypeDeclBinder(Name, 0)
            End Get
        End Property

        Public MustOverride Property UnderlyingType() As Type

        Public Overrides ReadOnly Property QualifiedName() As Qualifier
            Get
                Dim qb As New QualifierBuilder()
                qb.AppendQualifier(Parent.QualifiedName)
                If IsNested Then
                    qb.PushTypeSection(Name)
                Else
                    qb.PushNestedTypeSection(Name)
                End If

                Return qb.BuildQualifier()
            End Get
        End Property

        Public Overridable Function ResolveTypeDefinition() As Boolean
            Return False
        End Function

        Private m_isNested As Boolean
        Public Overridable Property IsNested() As Boolean
            Get
                Return m_isNested
            End Get
            Protected Set(ByVal value As Boolean)
                m_isNested = value
            End Set
        End Property

        Private m_nestedTypes As BindingTable(Of TypeDescription)
        Public ReadOnly Property NestedTypes() As BindingTable(Of TypeDescription)
            Get
                Return m_nestedTypes
            End Get
        End Property

        ''' <summary>
        ''' Find all nested types and create descriptions for them.
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overridable Function DeclareNestedTypes() As Boolean
            'get all sub declarations
            If SyntaxNode.Children.Count = 0 Then
                'no need to parse childs
                Return True
            End If

            Dim finalResult As Boolean = True

            For Each t As Tree In SyntaxNode.Children
                If TypeOf t Is Declaration Then
                    Try
                        'try to declare it
                        Dim newDescription = DeclareType(TryCast(t, Declaration))

                        'set as a nested type
                        newDescription.IsNested = True

                        'try to find re-declare
                        If Not NestedTypes.Enter(newDescription.IdentifyBinder, newDescription) Then
                            CompileUnit.SemanticErrorList.Add(New SemanticError(SemanticErrorType.TypeDefinitionConflict, t.Span, newDescription.Name))

                            finalResult = False
                        End If

                    Catch ex As ArgumentOutOfRangeException
                        'Not reconogized
                        'ignore

                        Continue For
                    End Try
                End If
            Next

            'all done, return the result
            Return finalResult
        End Function

        Public Overrides Function SearchChild(ByVal childBinder As Binder) As NameContainer
            'find in nested types

            Return NestedTypes.LookUp(childBinder)
        End Function
    End Class

    'Public Class NestedTypeDescription
    '    Inherits TypeDescription

    '    Private m_typeDescription As TypeDescription

    '    Public Sub New(ByVal nestedType As TypeDescription, ByVal declaringType As TypeDescription)
    '        MyBase.New(declaringType)
    '        m_typeDescription = nestedType
    '    End Sub

    '    Public ReadOnly Property DeclaringType() As TypeDescription
    '        Get
    '            Return CType(Parent, TypeDescription)
    '        End Get
    '    End Property

    '    Public Overrides Property SyntaxNode() As VBParser.Tree
    '        Get
    '            Return m_typeDescription.SyntaxNode
    '        End Get
    '        Set(ByVal value As VBParser.Tree)
    '            m_typeDescription.SyntaxNode = value
    '        End Set
    '    End Property

    '    Public Overrides Property UnderlyingType() As System.Type
    '        Get
    '            Return m_typeDescription.UnderlyingType
    '        End Get
    '        Set(ByVal value As System.Type)
    '            m_typeDescription.UnderlyingType = value
    '        End Set
    '    End Property

    '    Public Overrides ReadOnly Property QualifiedName() As Qualifier
    '        Get
    '            Dim qb As New QualifierBuilder()
    '            qb.AppendQualifier(Parent.QualifiedName)
    '            qb.PushNestedTypeSection(m_typeDescription.Name)

    '            Return qb.BuildQualifier()
    '        End Get
    '    End Property

    '    Public Overrides Function SearchChild(ByVal childBinder As Binder) As NameContainer
    '        Return m_typeDescription.SearchChild(childBinder)
    '    End Function

    '    Public Overrides Property Stage() As SemanticStage
    '        Get
    '            Return m_typeDescription.Stage
    '        End Get
    '        Protected Set(ByVal value As SemanticStage)
    '            Throw New InvalidOperationException("The Stage of a NestedTypeDescription is not able to be set.")
    '        End Set
    '    End Property
    'End Class

End Namespace

